package com.youbug.mall.service_ucs.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.youbug.common.constant.ChatConstant;
import com.youbug.common.to.UmsMemberTo;
import com.youbug.mall.service_ucs.dto.SessionInfo;
import com.youbug.mall.service_ucs.entity.UcsChat;
import com.youbug.mall.service_ucs.entity.UcsMessage;
import com.youbug.mall.service_ucs.service.*;
import com.youbug.system.service.ICustomerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

import static com.youbug.common.constant.AuthServerConstant.LOGIN_USER;


/**
 * @author websocket服务
 */
@ServerEndpoint(value = "/client/{userId}/{chatType}")
@Component
public class ClientWebSocket {

    private static final Logger logger = LoggerFactory.getLogger(ClientWebSocket.class);

    private ObjectMapper objectMapper = new ObjectMapper();
    private static ICustomerService customerService;
    private static IMessageService messageService;
    private static IChatService chatService;
    private static IStateService stateService;
    private static IQueueService queueService;
    private static ISenderService senderService;
    private static StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setService(IChatService chatService,IMessageService messageService,
                               ICustomerService customerService, IStateService stateService,
                               IQueueService queueService,ISenderService senderService,
                                StringRedisTemplate stringRedisTemplate) {
        ClientWebSocket.chatService = chatService;
        ClientWebSocket.messageService = messageService;
        ClientWebSocket.customerService = customerService;
        ClientWebSocket.stateService = stateService;
        ClientWebSocket.queueService = queueService;
        ClientWebSocket.senderService = senderService;
        ClientWebSocket.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) throws JsonProcessingException {
        String s = stringRedisTemplate.opsForValue().get(LOGIN_USER + ":" + userId);
        UmsMemberTo memberTo = objectMapper.readValue(s, UmsMemberTo.class);
        ChatsInfoHolder.clientSessionInfoMap.put(userId,
                new SessionInfo(ChatConstant.CLIENT, userId, memberTo.getNickname(), session));
    }

    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userId") Long userId, @PathParam("chatType") String chatType) throws IOException {

        UcsMessage msg = objectMapper.readValue(message, UcsMessage.class);
        if(ChatConstant.MSG_TYPE_KEEPALIVE.equals(msg.getType())){
            return;
        }
        msg.setSender(ChatConstant.CLIENT);
        msg.setSenderId(userId);
        msg.setCreateTime(new Date());
        if(isMalaoshiMsg(session, msg)){return;}
        SessionInfo sessionInfo = ChatsInfoHolder.clientSessionInfoMap.get(userId);
        UcsChat ucsChat = sessionInfo.getHoldUcsChat();
        if(ucsChat == null){
            if(!ChatConstant.MSG_TYPE_CLOSE.equals(msg.getType())){
                ucsChat = new UcsChat();

                ucsChat.setState(ChatConstant.CHAT_STATE_WAITTING);
                ucsChat.setClientId(userId);
                ucsChat.setClientName(sessionInfo.getUserName());
                ucsChat.setType(chatType);
                ucsChat.setBeginTime(LocalDateTime.now());

                chatService.save(ucsChat);
                msg.setChatId(ucsChat.getId());
                saveMsg(msg, userId);
                session.getBasicRemote().sendText(objectMapper.writeValueAsString(ChatConstant.IN_QUEUE_MSG));

                queueService.toQueueUp(ucsChat);
                sessionInfo.setHoldUcsChat(ucsChat);
            }
        }else{
            msg.setChatId(ucsChat.getId());
              if(ChatConstant.MSG_TYPE_CLOSE.equals(msg.getType())){
                  closeChat(userId);
              }else{
                  saveMsg(msg, userId);
              }
              if(ChatConstant.CHAT_STATE_TALKING.equals(ucsChat.getState())){
                  senderService.sendMsgToAgent(ucsChat.getAgentId(), msg);
              }
        }
        session.getBasicRemote().sendText(objectMapper.writeValueAsString(msg));
    }

    private void saveMsg(UcsMessage msg, Long userId){
        msg.setSenderId(userId);
        msg.setSender(ChatConstant.CLIENT);
        messageService.save(msg);
    }

    private boolean isMalaoshiMsg(Session session, UcsMessage msg) throws IOException {

        if(MLSAutoAnswer.msgMap.keySet().contains(msg.getContent())){// 全匹配，自动回复
            List<UcsMessage> msgs = MLSAutoAnswer.getMsg(msg);
            if(!CollectionUtils.isEmpty(msgs)){
                session.getBasicRemote().sendText(objectMapper.writeValueAsString(msg));
                try {
                    Thread.sleep((int)(Math.random() * 2000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (UcsMessage vo : msgs){
                    try {
                        Thread.sleep((int)(Math.random() * 1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    session.getBasicRemote().sendText(objectMapper.writeValueAsString(vo));
                }
                return true;
            }
        }
        return false;
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId") Long userId) {
        // 客户端断开
        logger.info("onClose,客户端断开"+userId);
        closeChat(userId);
        ChatsInfoHolder.clientSessionInfoMap.remove(userId);
    }

    @OnError
    public void onError(Session session, Throwable error, @PathParam("userId") Long userId){
        closeChat(userId);
        ChatsInfoHolder.clientSessionInfoMap.remove(userId);
        try {
            session.close();
        } catch (IOException e) {
            logger.info("clientOnError", error);
            throw new RuntimeException(error);
        }
    }

    private void closeChat(Long userId){
        SessionInfo sessionInfo = ChatsInfoHolder.clientSessionInfoMap.get(userId);
        UcsChat holdUcsChat;
        if(sessionInfo != null && (holdUcsChat = sessionInfo.getHoldUcsChat()) != null){
            if(ChatConstant.CHAT_STATE_WAITTING.equals(holdUcsChat.getState())){
                queueService.stopWaiting(holdUcsChat);
                queueService.broadcastQueueInfo();
            }
            UcsChat ucsChat = new UcsChat();
            ucsChat.setId(holdUcsChat.getId());
            ucsChat.setState(ChatConstant.CHAT_STATE_CLOSED);
            ucsChat.setEndTime(LocalDateTime.now());

            boolean update = chatService.updateById(ucsChat);
        }
        logger.info("会话结束"+userId);
    }
}
